package com.qire.other.thirdPlatform;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Message;

import com.qire.other.thirdPlatform.authorize.ThirdPlatformAuthorization;
import com.qire.other.thirdPlatform.authorize.ThirdPlatformAuthorizeCallBack;
import com.qire.other.thirdPlatform.authorize.ThirdPlatformUserInfo;
import com.qire.other.thirdPlatform.pay.ThirdPlatformPay;
import com.qire.other.thirdPlatform.pay.ThirdPlatformPayCallBack;
import com.qire.other.thirdPlatform.uikit.NetworkUtil;
import com.qire.other.thirdPlatform.WeChatPlatform.PayParam;
import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;

/**
 * 微信平台认证支付相关操作
 */
public class WeChatPlatform extends ThirdPlatform implements ThirdPlatformAuthorization, ThirdPlatformPay<PayParam> {

	public static final WeChatPlatform WeChat = new WeChatPlatform();

	// APP_ID 替换为你的应用从官方网站申请到的合法appID
	public final String WE_CHAT_APP_ID = "wxa9ed2f3d0b3ba8a7";
	// APP_SECRET
	public final String WE_CHAT_APP_SECRET = "73354c76b1f974403286e603c4dd8ab4";
	// IWXAPI 是第三方app和微信通信的openApi接口
	private IWXAPI weChatApi;

	public static final int MSG_PAY_BACK = 102;

	public static final int Authorization = 101;
	public static final int GET_TOKEN = 1;
	public static final int CHECK_TOKEN = 2;
	public static final int REFRESH_TOKEN = 3;
	public static final int GET_USER_INFO = 4;


	private ThirdPlatformAuthorizeCallBack authorizeCallBack;
	private ThirdPlatformPayCallBack payCallBack;

	private AuthorizationInfo authorizationInfo;

	private WeChatPlatform() { }

	public void init(Context context) {

		// 通过WXAPIFactory工厂，获取IWXAPI的实例
		weChatApi = WXAPIFactory.createWXAPI(context, WE_CHAT_APP_ID, true);

		// 将应用的appId注册到微信
		weChatApi.registerApp(WE_CHAT_APP_ID);

		//建议动态监听微信启动广播进行注册到微信
		context.registerReceiver(new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				// 将该app注册到微信
				weChatApi.registerApp(WE_CHAT_APP_ID);
			}
		}, new IntentFilter(ConstantsAPI.ACTION_REFRESH_WXAPP));

	}

	public IWXAPI weChatApi() {
		return weChatApi;
	}

	@Override
	public void goPay(PayParam payParam, Activity activity, ThirdPlatformPayCallBack callBack) {

		this.payCallBack = callBack;

		boolean isPaySupported = weChatApi.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
		if(!isPaySupported){
			System.out.println("设备不支持微信支付");
			if(callBack != null) {
				callBack.callBack("error", PAY_ERROR, payParam.outTradeNo);
			}
			return;
		}

		PayReq req = new PayReq();
		//req.appId = "wxf8b4f85f3a794e77";  // 测试用appId
		req.appId			= payParam.appId;
		req.partnerId		= payParam.partnerId;
		req.prepayId		= payParam.prepayId;
		req.nonceStr		= payParam.nonceStr;
		req.timeStamp		= payParam.timeStamp;
		req.packageValue	= "Sign=WXPay";
		req.sign			= payParam.sign;
		req.extData			= payParam.outTradeNo; //"app data"; // optional
		weChatApi.sendReq(req);
	}

	@Override
	public void authorize(ThirdPlatformAuthorizeCallBack callBack) {
		authorizeCallBack = callBack;

		if(!weChatApi.isWXAppInstalled()) {
			callBack.callBack("微信未安装，请先安装微信", null);
			return;
		}

		final SendAuth.Req req = new SendAuth.Req();
		req.scope = "snsapi_userinfo";
		req.state = "qiremanhua";
		weChatApi.sendReq(req);
	}

	@Override
	public void destroy() {
		super.destroy();
		weChatApi.unregisterApp();
	}

	@Override
	public void handleMessage(Message msg) {
		int tag = msg.what;
		switch (tag) {
			case MSG_PAY_BACK: {
				noticePaymentResult(msg.getData());
				break;
			}
			case Authorization: {
				queryAccessToken(msg.getData());
				break;
			}
			case GET_TOKEN: {
				queryUserInfo(msg.getData());
				break;
			}
			case GET_USER_INFO: {
				returnUserInfo(msg.getData());
				break;
			}
		}
	}

	private void noticePaymentResult(Bundle bundle) {
		String outTradeNo = bundle.getString("extData");
		int payCode = bundle.getInt("resultCode");
		if(payCallBack != null) {
			payCallBack.callBack("", payCode, outTradeNo);
		}
	}

	private void queryAccessToken(Bundle bundle) {

		authorizationInfo = new AuthorizationInfo();
		authorizationInfo.ErrCode = bundle.getInt("ErrCode");
		authorizationInfo.code	  = bundle.getString("code");
		authorizationInfo.state	  = bundle.getString("state");
		authorizationInfo.lang	  = bundle.getString("lang");
		authorizationInfo.country = bundle.getString("country");

		final String code = authorizationInfo.code;

		System.out.println("authorizationInfo ==" + code);

		String apiUrl = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?" +
						"appid=%s&secret=%s&code=%s&grant_type=authorization_code", WE_CHAT_APP_ID, WE_CHAT_APP_SECRET, code);
		NetworkUtil.sendWxAPI(this, apiUrl, GET_TOKEN);
	}

	private void queryUserInfo(Bundle bundle) {
		try {
			if(bundle.isEmpty()) {
				if(authorizeCallBack != null) {
					authorizeCallBack.callBack("微信登录唤起失败", null);
				}
				return;
			}

			JSONObject json = new JSONObject(bundle.getString("result"));

			if(json.has("errcode")) {
				switch (json.getInt("errcode")) {
					case 40029 :
						if(authorizeCallBack != null) {
							authorizeCallBack.callBack("取消登录", null);
							return;
						}
				}
			}

			authorizationInfo.openId		= json.getString("openid");
			authorizationInfo.unionid		= json.getString("unionid");
			authorizationInfo.accessToken	= json.getString("access_token");
			authorizationInfo.expiresIn		= json.getInt("expires_in");
			authorizationInfo.refreshToken	= json.getString("refresh_token");
			authorizationInfo.scope			= json.getString("scope");

			String apiUrl = String.format("https://api.weixin.qq.com/sns/userinfo?" +
							"access_token=%s&openid=%s", authorizationInfo.accessToken, authorizationInfo.openId);
			NetworkUtil.sendWxAPI(this, apiUrl, GET_USER_INFO);

		} catch (JSONException e) {
			System.out.println(e.getMessage());
			if(authorizeCallBack != null)
				authorizeCallBack.callBack("登录失败",null);
		}

	}

	private void returnUserInfo(Bundle bundle) {
		destroy();
		try {
			JSONObject json = new JSONObject(bundle.getString("result"));

			String encode = getCode(json.getString("nickname"));
			ThirdPlatformUserInfo userInfo = new ThirdPlatformUserInfo();
			userInfo.openid			= json.getString("openid");
			userInfo.unionid		= json.getString("unionid") ;
			userInfo.headimgurl 	= json.getString("headimgurl");
			userInfo.nickname		= new String(json.getString("nickname").getBytes(encode), "utf-8");
			userInfo.sex			= json.getString("sex");
			userInfo.province		= json.getString("province");
			userInfo.city			= json.getString("city");
			userInfo.country		= json.getString("country");
			userInfo.accessToken	= authorizationInfo.accessToken;

			if(authorizeCallBack != null)
				authorizeCallBack.callBack("complete",userInfo);
		} catch (JSONException | UnsupportedEncodingException e) {
			System.out.println(e.getMessage());
			if(authorizeCallBack != null)
				authorizeCallBack.callBack("error",null);
		}

	}

	private String getCode(String str) {
		String[] encodeArray = {"GB2312", "ISO-8859-1", "UTF-8", "GBK", "Big5", "UTF-16LE", "Shift_JIS", "EUC-JP"};
		for(int i = 0; i < encodeArray.length; i++) {
			try {
				if (str.equals(new String(str.getBytes(encodeArray[i]), encodeArray[i]))) {
					return encodeArray[i];
				}
			} catch (Exception e) {

			} finally {

			}
		}
		return "";
	}

	private class AuthorizationInfo {
		private String	openId;
		private String	unionid;
		private String	accessToken;
		private int		expiresIn;
		private String	refreshToken;
		private String	scope;

		private int    	ErrCode	;//ERR_OK = 0(用户同意) ERR_AUTH_DENIED = -4（用户拒绝授权） ERR_USER_CANCEL = -2（用户取消）
		private String	code	;//用户换取 access_token 的 code，仅在 ErrCode 为 0 时有效
		private String	state	;//第三方程序发送时用来标识其请求的唯一性的标志，由第三方程序调用 sendReq 时传入，由微信终端回传，state 字符串长度不能超过 1K
		private String	lang	;//微信客户端当前语言
		private String	country	;//微信用户当前国家信息
	}

	public static class PayParam {
		private final String appId;
		private final String partnerId;
		private final String prepayId;
		private final String nonceStr;
		private final String timeStamp;
		private final String sign;
		// app后台系统生成对账的外部订单号
		private final String outTradeNo;

		public PayParam(String appId, String partnerId, String prepayId, String nonceStr, String timeStamp, String sign, String outTradeNo) {
			this.appId = appId;
			this.partnerId = partnerId;
			this.prepayId = prepayId;
			this.nonceStr = nonceStr;
			this.timeStamp = timeStamp;
			this.sign = sign;
			this.outTradeNo = outTradeNo;
		}
	}
}
